#!/bin/bash

PATH=/bin:/usr/bin:/sbin:/usr/sbin
LANG=C
LC_ALL=C

#set -e

LOGFILE=/var/log/$(basename $0).log
USER=ubuntu
SSHDIR=/home/${USER}/.ssh
KEYSPATH=${SSHDIR}/authorized_keys

METADATA_LOCATION=drive
METADATA_DRIVE_MOUNTPOINT=/metadata
METADATA_ISO_MOUNTPOINT=/mnt/metadata_cd

function get_metadata_from_server() {
  local param=$1
  curl -s --retry 3 http://169.254.169.254/latest/meta-data/${param}
}

function get_userdata_from_server() {
  curl -s --retry 3 http://169.254.169.254/latest/user-data
}

function get_metadata_from_drive() {
  local param=$1
  local param_path=${METADATA_DRIVE_MOUNTPOINT}/meta-data/${param}

  if [ -d ${param_path} ]; then
    ls ${param_path}
  elif [ -f ${param_path} ]; then
    cat ${param_path}
  else
    exit 1
  fi
}

function get_userdata_from_drive() {
  cat ${METADATA_DRIVE_MOUNTPOINT}/user-data
}

function get_metadata() {
  local param=$1
  for i in {1..10}; do
    get_metadata_from_${METADATA_LOCATION} ${param} && exit 0
    sleep 3
  done
  exit 1
}

function get_userdata() {
  for i in {1..10}; do
    get_userdata_from_${METADATA_LOCATION} ${param} && exit 0
    sleep 3
  done
  exit 1
}

function logger() {
  tee -a ${LOGFILE}
}


case "$1" in
ms|metadata-server)
  METADATA_LOCATION=server
  ;;
md|metadata-drive)
  METADATA_LOCATION=drive
  ;;
mcd|metadata-cd)
  # Mount the metadata CD and setup the image inside
  # to be used as metadata drive
  if [ ! -d ${METADATA_ISO_MOUNTPOINT} ]; then
    mkdir -p ${METADATA_ISO_MOUNTPOINT}
  fi
  mount LABEL=META_CD ${METADATA_ISO_MOUNTPOINT}
  /sbin/losetup `/sbin/losetup -f` ${METADATA_ISO_MOUNTPOINT}/metadata.img

  METADATA_LOCATION=drive
  ;;
*)
  METADATA_LOCATION=drive
  ;;
esac

case "$METADATA_LOCATION" in
drive)
  if [[ -f /proc/vz/veinfo ]]; then
    # OpenVZ mounts metadata drive from the outside script.
    METADATA_DRIVE_MOUNTPOINT="/metadata"
  else
    mount_output=`mount -l | grep -w METADATA | cut -d " " -f3`
    [[ -z "${mount_output}" ]] || {
      # already mounted
      METADATA_DRIVE_MOUNTPOINT="${mount_output}"
    }


    if mountpoint -q "${MEATADATA_DRIVE_MOUNTPOINT}"; then
      echo "Metadata drive already mounted on: ${METADATA_DRIVE_MOUNTPOINT}"
    else
      if [ ! -d ${METADATA_DRIVE_MOUNTPOINT} ]; then
	echo "Creating directory: ${METADATA_DRIVE_MOUNTPOINT}"
	mkdir ${METADATA_DRIVE_MOUNTPOINT}
      fi
      echo "Mounting metadata drive on: ${METADATA_DRIVE_MOUNTPOINT}"
      mount LABEL=METADATA ${METADATA_DRIVE_MOUNTPOINT} || {
	echo no such labeled device: METADATA | logger
	exit 1
      }
      echo "Mounted metadata drive successfully on: ${METADATA_DRIVE_MOUNTPOINT}"
    fi
  fi
  ;;
server)
  ;;
*)
  exit 0
  ;;
esac


# Set up the host name
HN=`get_metadata local-hostname`
if [ -n "$HN" ]; then
  echo "Setting the hostname"
  grep -q "$HN" /etc/hostname
  if [ $? -ne 0 ]; then
    hostname $HN
    echo $HN > /etc/hostname
  fi

  # Add it to the hosts file if not there yet
  grep -q "$HN" /etc/hosts
  if [ $? -ne 0 ]; then
    echo '127.0.0.1 '$HN >> /etc/hosts
  fi
fi

# Set up the authorized keys for the users to login
KEYS=`get_metadata public-keys/0/openssh-key`
if [ -n "$KEYS" ]; then
  echo "Setting authorized keys" | logger
  [ -d ${SSHDIR} ] || {
    mkdir -m 700 ${SSHDIR}
    chown ${USER}:${USER} ${SSHDIR}
  }
  # Check if the keys are already authorized
  [ -f $KEYSPATH ] && grep -q "$KEYS" $KEYSPATH
  if [ $? -ne 0 ]; then
    echo $KEYS > $KEYSPATH
    chmod 600 $KEYSPATH
    chown ${USER} $KEYSPATH
  fi
fi

# Generate ssh host keys
if [ ! -f /etc/ssh/ssh_host_rsa_key ]; then
  echo "Generating ssh host keys"
  dpkg-reconfigure openssh-server
fi

# Set up network configuration
case "$METADATA_LOCATION" in
#drive|server)
drive)
  echo "Detecting default gateway."
  gateway=$(
    for macaddr in $(get_metadata network/interfaces/macs/); do
      mac_path=network/interfaces/macs/${macaddr%%/}
      gateway=`get_metadata ${mac_path}/x-gateway`
      metric=`get_metadata ${mac_path}/x-metric`
      echo ${metric} ${gateway}
    done | sort -n -k 1 | head -1 | while read metric gateway; do
      echo ${gateway}
    done
  )
  echo "Detected gateway is ${gateway}"

  cat <<NETINIT > /etc/network/interfaces
# Generated by Wakame-VDC

auto lo
iface lo inet loopback

NETINIT

  for macaddr in $(get_metadata network/interfaces/macs/); do
    mac_path=network/interfaces/macs/${macaddr%%/}
    mac=`get_metadata ${mac_path}/mac`

    nic=`ifconfig -a | grep -i $mac | tr -s ' ' | cut -d ' ' -f1`

    ip=`get_metadata ${mac_path}/local-ipv4s`
    broadcast=`get_metadata ${mac_path}/x-broadcast`

    gateway=`get_metadata ${mac_path}/x-gateway`
    metric=`get_metadata ${mac_path}/x-metric`
    netmask=`get_metadata ${mac_path}/x-netmask`
    network=`get_metadata ${mac_path}/x-network`
    dns=`get_metadata ${mac_path}/x-dns`

    cat <<INTERFACE >> /etc/network/interfaces
auto ${nic}
iface ${nic} inet static
  address ${ip}
  network ${network}
  netmask ${netmask}
  broadcast ${broadcast}
  metric ${metric}
INTERFACE

    if [ ! -z ${gateway} ]; then
      echo "  gateway ${gateway}" >> /etc/network/interfaces
    fi
    echo "" >> /etc/network/interfaces

    if [ ! -z ${dns} ]; then
      grep -q "nameserver ${dns}" /etc/resolv.conf
      [ $? == 0 ] || echo nameserver ${dns} >> /etc/resolv.conf
    fi
  done

  /etc/init.d/networking restart

  [ -z ${gateway} ] || route add default gw ${gateway}
  ;;
*)
  ;;
esac | logger

#Add the metadata server to the routing table
#for i in {1..1200}; do
#  DEFAULT_GW=`ip route get 8.8.8.8 | head -n 1 | cut -d ' ' -f3`
#  echo ... ${i} DEFAULT_GW=${DEFAULT_GW} | logger
#  [ -z "${DEFAULT_GW}" ] || break
#  sleep 3
#done
#[ -z ${DEFAULT_GW} ] || route add 169.254.169.254 gateway $DEFAULT_GW

# Important for remote storage.
sync
